use nacos_rust_client::client::naming_client::{NamingClient, QueryInstanceListParams};
use std::sync::Arc;
use tonic::{Request, Response, Status};

use crate::rpc::proto::{
    system_auth::{auth_server::Auth, LoginByAccountReq, LoginByAccountRes},
    infra_dict::{dict_client::DictClient, GetDataListReq as DictReq},
    infra_notice::{notice_client::NoticeClient, SendNoticeReq as NoticeReq},
};

#[derive(Clone)]
pub struct MyAuth {
    naming_client: Arc<NamingClient>,
}

impl MyAuth {
    pub fn new(naming_client: Arc<NamingClient>) -> Self {
        Self { naming_client }
    }

    async fn get_infra_service_endpoint(&self, service_name: &str) -> Result<String, Status> {
        let params = QueryInstanceListParams::new_simple(service_name, "DEFAULT_GROUP");
        match self.naming_client.select_instance(params).await {
            Ok(instance) => {
                let endpoint = format!("http://{}:{}", instance.ip, instance.port);
                Ok(endpoint)
            }
            Err(e) => {
                eprintln!("获取 {} 服务实例失败: {:?}", service_name, e);
                Err(Status::unavailable(format!("服务 {} 不可用", service_name)))
            }
        }
    }

    async fn handle_login(&self, username: &str, login_type: &str) -> Result<LoginByAccountRes, Status> {
        // 调用字典服务获取用户权限信息
        let dict_endpoint = self.get_infra_service_endpoint("infra-dict").await?;
        let mut dict_client = DictClient::connect(dict_endpoint)
            .await
            .map_err(|e| Status::internal(format!("连接字典服务失败: {}", e)))?;

        let dict_request = tonic::Request::new(DictReq {
            name: "用户权限".to_string(),
        });

        let dict_response = dict_client
            .get_data_list(dict_request)
            .await
            .map_err(|e| Status::internal(format!("调用字典服务失败: {}", e)))?;

        // 发送登录通知
        let notice_endpoint = self.get_infra_service_endpoint("infra-notice").await?;
        let mut notice_client = NoticeClient::connect(notice_endpoint)
            .await
            .map_err(|e| Status::internal(format!("连接通知服务失败: {}", e)))?;

        let notice_request = tonic::Request::new(NoticeReq {
            title: "用户登录通知".to_string(),
            content: format!("用户 {} 通过{}方式登录", username, login_type),
        });

        let _notice_response = notice_client
            .send_notice(notice_request)
            .await
            .map_err(|e| Status::internal(format!("调用通知服务失败: {}", e)))?;

        Ok(LoginByAccountRes {
            message: format!(
                "{}登录成功! 用户: {}, 权限信息: {}",
                login_type,
                username,
                dict_response.into_inner().message
            ),
        })
    }
}

#[tonic::async_trait]
impl Auth for MyAuth {
    async fn login_by_account(
        &self,
        request: Request<LoginByAccountReq>,
    ) -> Result<Response<LoginByAccountRes>, Status> {
        println!("Auth服务收到账号登录请求: {:?}", request.remote_addr());
        let req = request.into_inner();
        
        let reply = self.handle_login(&req.name, "账号").await?;
        Ok(Response::new(reply))
    }

    async fn login_by_mobile(
        &self,
        request: Request<LoginByAccountReq>,
    ) -> Result<Response<LoginByAccountRes>, Status> {
        println!("Auth服务收到手机号登录请求: {:?}", request.remote_addr());
        let req = request.into_inner();
        
        let reply = self.handle_login(&req.name, "手机号").await?;
        Ok(Response::new(reply))
    }
} 